Header file compact_optional.hpp

namespace type_safe
{
    template <class CompactPolicy>
    class compact_optional_storage;
    
    template <class CompactPolicy>
    using compact_optional = basic_optional<compact_optional_storage<CompactPolicy>>;
    
    template <typename Boolean>
    class compact_bool_policy;
    
    template <typename Integer, Integer Invalid>
    class compact_integer_policy;
    
    template <typename FloatingPoint>
    class compact_floating_point_policy;
    
    template <typename Enum, 'hidden' Invalid>
    class compact_enum_policy;
    
    template <class Container>
    class compact_container_policy;
}

Class template type_safe::compact_optional_storage [optional]

template <class CompactPolicy>
class compact_optional_storage
{
public:
    using value_type = typename std::remove_cv<typename CompactPolicy::value_type>::type;
    
    using storage_type = typename CompactPolicy::storage_type;
    
    using lvalue_reference = 'hidden';
    
    using const_lvalue_reference = 'hidden';
    
    using rvalue_reference = 'hidden';
    
    using const_rvalue_reference = 'hidden';
    
    template <typename U>
    using rebind = direct_optional_storage<U>;
    
    compact_optional_storage() noexcept;
    
    template <typename ... Args>
    typename std::enable_if<std::is_constructible<value_type, Args&&...>::value>::type create_value(Args&&... args);
    
    void create_value(const compact_optional_storage& other);
    
    void create_value(compact_optional_storage&& other);
    
    void create_value_explicit();
    
    void copy_value(const compact_optional_storage& other);
    
    void copy_value(compact_optional_storage&& other);
    
    void swap_value(compact_optional_storage& other);
    
    void destroy_value() noexcept;
    
    bool has_value() const noexcept;
    
    lvalue_reference get_value() & noexcept;
    const_lvalue_reference get_value() const & noexcept;
    rvalue_reference get_value() && noexcept;
    const_rvalue_reference get_value() const && noexcept;
    
    template <typename U, typename = typename std::enable_if<std::is_copy_constructible<value_type>::value&&std::is_convertible<U&&, value_type>::value>::type>
    value_type get_value_or(U&& u) const &;
    
    template <typename U>
    value_type get_value_or(U&& u) &&;
};

A StoragePolicy for ts::basic_optional that is more space efficient than ts::direct_optional_storage.

It is designed to have no space overhead compared to a regular object of the stored type. This is accomplished by marking one value of the stored type as invalid and using that in the empty state. What the invalid value is is controlled by the CompactPolicy. It must provide the following static member functions and typedefs:

In the cases where value_type and storage_type differ, the get_value() functions will not return references, but a copy instead. The implementation assumes that invalid_value() and is_invalid() are noexcept and cheap.

Notes: For a compact optional of pointer type, use ts::optional_ref.

Default constructor type_safe::compact_optional_storage::compact_optional_storage

compact_optional_storage() noexcept;

Effects: Initializes it in the state without value, i.e. sets the storage to the invalid value.

Function template type_safe::compact_optional_storage::create_value

template <typename ... Args>
typename std::enable_if<std::is_constructible<value_type, Args&&...>::value>::type create_value(Args&&... args);

Effects: Creates a temporary value_type by perfectly forwarding args, converts that to the storage_type and assigns it. Afterwards has_value() will return true.

Throws: Anything thrown by the constructor of value_type/storage_type or its move assignment operator in which case has_value() is still false. \requires has_value() == false and the given value must not be invalid. \notes This function does not participate in overload resolution unless value_type is constructible from args. \synopsis template

Function type_safe::compact_optional_storage::create_value

void create_value(const compact_optional_storage& other);

Effects: Copy assigns the storage_type.

Function type_safe::compact_optional_storage::create_value

void create_value(compact_optional_storage&& other);

Effects: Move assigns the storage_type.

Function type_safe::compact_optional_storage::copy_value

void copy_value(const compact_optional_storage& other);

Effects: Copy assigns the storage_type.

Function type_safe::compact_optional_storage::copy_value

void copy_value(compact_optional_storage&& other);

Effects: Move assigns the storage_type.

Function type_safe::compact_optional_storage::swap_value

void swap_value(compact_optional_storage& other);

Effects: Swaps the storage_type.

Function type_safe::compact_optional_storage::destroy_value

void destroy_value() noexcept;

Effects: Destroys the value by setting it to the invalid storage value. Afterwards has_value() will return false.

Requires: has_value() == true.

Function type_safe::compact_optional_storage::has_value

bool has_value() const noexcept;

Returns: Whether or not there is a value stored, i.e. whether the stored value is not invalid.

Function type_safe::compact_optional_storage::get_value

(1)  lvalue_reference get_value() & noexcept;

(2)  const_lvalue_reference get_value() const & noexcept;

(3)  rvalue_reference get_value() && noexcept;

(4)  const_rvalue_reference get_value() const && noexcept;

Returns: A (suitable) reference to the stored value or a copy of the value depending on the policy.

Requires: has_value() == true.

Function template type_safe::compact_optional_storage::get_value_or

template <typename U, typename = typename std::enable_if<std::is_copy_constructible<value_type>::value&&std::is_convertible<U&&, value_type>::value>::type>
value_type get_value_or(U&& u) const &;

Returns: Either get_value() or u converted to value_type.

Requires: value_type must be copy (1)/move (2) constructible and u convertible to value_type. \group get_value_or \param 1 \exclude

Function template type_safe::compact_optional_storage::get_value_or

(1)  template <typename U>
     value_type get_value_or(U&& u) &&;


Alias template type_safe::compact_optional

template <class CompactPolicy>
using compact_optional = basic_optional<compact_optional_storage<CompactPolicy>>;

An alias for ts::basic_optional using ts::compact_optional_storage with the given CompactPolicy. \module optional

Class template type_safe::compact_bool_policy

template <typename Boolean>
class compact_bool_policy
{
public:
    using value_type = Boolean;
    
    using storage_type = char;
    
    static storage_type invalid_value() noexcept;
    
    static bool is_invalid(storage_type storage) noexcept;
};

A CompactPolicy for ts::compact_optional_storage for boolean types.

It is designed for either bool or ts::boolean.

Notes: It uses a different storage_type and thus cannot return a reference to the stored value. \module optional

Class template type_safe::compact_integer_policy

template <typename Integer, Integer Invalid>
class compact_integer_policy
{
public:
    using value_type = Integer;
    
    using storage_type = Integer;
    
    static storage_type invalid_value() noexcept;
    
    static bool is_invalid(const storage_type& storage) noexcept;
};

A CompactPolicy for ts::compact_optional_storage for integer types.

The given Invalid value will be used to mark an empty optional.

Class template type_safe::compact_floating_point_policy [optional]

template <typename FloatingPoint>
class compact_floating_point_policy
{
public:
    using value_type = FloatingPoint;
    
    using storage_type = FloatingPoint;
    
    static storage_type invalid_value() noexcept;
    
    static bool is_invalid(const storage_type& storage) noexcept;
};

A CompactPolicy for ts::compact_optional_storage for floating point types.

NaN will be used to mark an empty optional.

Class template type_safe::compact_enum_policy

template <typename Enum, 'hidden' Invalid>
class compact_enum_policy
{
public:
    using value_type = Enum;
    
    using storage_type = 'hidden';
    
    static storage_type invalid_value() noexcept;
    
    static bool is_invalid(const storage_type& storage) noexcept;
};

A CompactPolicy for ts::compact_optional_storage for enumeration types.

It uses the given Invalid value of the underlying type to mark an empty optional.

Notes: It uses a different storage_type and thus cannot return a reference to the stored value. \module optional

Class template type_safe::compact_container_policy

template <class Container>
class compact_container_policy
{
public:
    using value_type = Container;
    
    using storage_type = Container;
    
    static storage_type invalid_value() noexcept;
    
    static bool is_invalid(const storage_type& storage) noexcept;
};

A CompactPolicy for ts::compact_optional_storage for container types.

A Container is a type with a cheap no-throwing default constructor initializing it empty, and either an empty() member function or ADL function that returns true if the container is empty, false otherwise. An empty container will be marked as an empty optional. \module optional